using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Xfinity.AI;
using Xfinity.AI.Entities;
using Xfinity.Engine.SceneGraph;
#if!XBOX
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework.Content;
using Xfinity.ParticleSystems;
#endif
namespace Xfinity.Levels
{
    /// <summary>
    /// A complete level description.
    /// </summary>
    [Serializable]
    public class Level : DrawableGameComponent
    {
        public override void Draw(GameTime gameTime)
        {
            sceneGraph.Draw(gameTime);
            foreach (ParticleSystem system in particleSystems)
            {
                system.Draw(gameTime);
            }

            base.Draw(gameTime);
        }

        public static Level Load(string filename)
        {
            using (FileStream stream = new FileStream(filename, FileMode.Open))
            {
                return Load(stream);
            }

        }

        public static Level Load(Stream stream)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Level));
            return (Level)serializer.Deserialize(stream);
        }
        public Level():base(GameManager.Game)
        {
            
        }

        private static ContentManager content;
        
        public static Level LoadFromContentFile(string fileName)
        {
            content = GameManager.Content;
            return content.Load<Level>(fileName);
        }


        private DateTime dateCreated;

        /// <summary>
        /// Gets or sets the date the level was created.
        /// </summary>
        /// <value>The date created.</value>
#if !XBOX
        [ReadOnly(true)]
#endif
        public DateTime DateCreated
        {
            get { return dateCreated; }
            set { dateCreated = value; }
        }

        private DateTime dateLastModified;

        /// <summary>
        /// Gets or sets the level was last edited.
        /// </summary>
        /// <value>The date last modified.</value>
#if !XBOX
        [ReadOnly(true)]
#endif
        public DateTime DateLastModified
        {
            get { return dateLastModified; }
            set { dateLastModified = value; }
        }


        private string name = String.Empty;

        /// <summary>
        /// Gets or sets the name of the level.
        /// </summary>
        /// <value>The name.</value>
        [XmlAttribute()]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Level"/> class.
        /// </summary>
        /// <param name="models">The models.</param>
        /// <param name="logic">The logic.</param>
        public Level(IEnumerable<PhysicalEntity> models, IEnumerable<LogicalEntity> logic)
            : base(GameManager.Game)
        {
            sceneGraph = new SceneGraph(models, GameManager.Game);
            if (logic != null)
            {
                this.logic = new List<LogicalEntity>(logic);
            }
            else
            {
                this.logic = new List<LogicalEntity>();
            }
        }


        private SceneGraph sceneGraph = new SceneGraph();

        /// <summary>
        /// Gets the scene graph.
        /// </summary>
        /// <value>The scene graph.</value>
        public SceneGraph SceneGraph
        {
            get { return sceneGraph; }
        }

        private List<LogicalEntity> logic = new List<LogicalEntity>();

        /// <summary>
        /// Gets the logic.
        /// </summary>
        /// <value>The logic.</value>
        public List<LogicalEntity> Logic
        {
            get { return logic; }
        }

        private SquadCollection squads = new SquadCollection();

        public SquadCollection Squads
        {
            get { return squads; }
        }

        private List<Waypoint> waypoints = new List<Waypoint>();

        /// <summary>
        /// Gets or sets the waypoints.
        /// </summary>
        /// <value>The waypoints.</value>
        public List<Waypoint> Waypoints
        {
            get { return waypoints; }
        }

        private AgentCollection agents = new AgentCollection();

        public List<PhysicalEntity> Entities
        {
            get { return sceneGraph.Root.Entities; }
        }

        /// <summary>
        /// Gets the agents.
        /// </summary>
        /// <value>The agents.</value>
        public AgentCollection Agents
        {
            get { return agents; }
        }

        private List<ParticleSystem> particleSystems = new List<ParticleSystem>();

        /// <summary>
        /// 
        /// </summary>
        public List<ParticleSystem> ParticleSystems
        {
            get { return particleSystems; }
            set { particleSystems = value; }
        }


        private PlayerStartInformation playerStartInformation = new PlayerStartInformation();

        /// <summary>
        /// Gets or sets the player start information.
        /// </summary>
        /// <value>The player start information.</value>
        public PlayerStartInformation PlayerStartInformation
        {
            get { return playerStartInformation; }
            set { playerStartInformation = value; }
        }
    }

    #region Support classes
    [Serializable]
    public class PlayerStartInformation
    {
#if !XBOX
        [Browsable(false)]
#endif
        public string Name
        {
            get { return "Player start information"; }
        }

        private Vector3 playerStartPosition;

        /// <summary>
        /// Gets or sets the player start position.
        /// </summary>
        /// <value>The player start position.</value>
#if !XBOX
        [TypeConverter(typeof(Vector3Converter))]
#endif
        public Vector3 PlayerStartPosition
        {
            get { return playerStartPosition; }
            set { playerStartPosition = value; }
        }

        private Vector3 playerStartOrientation;

        /// <summary>
        /// Gets or sets the player start orientation.
        /// </summary>
        /// <value>The player start orientation.</value>
#if !XBOX
        [TypeConverter(typeof(Vector3Converter))]
#endif
        public Vector3 PlayerStartOrientation
        {
            get { return playerStartOrientation; }
            set { playerStartOrientation = value; }
        }

        private float playerStartHealth = 100;

        /// <summary>
        /// Gets or sets the player start health.
        /// </summary>
        /// <value>The player start health.</value>
        public float PlayerStartHealth
        {
            get { return playerStartHealth; }
            set { playerStartHealth = value; }
        }
    }

    public class Waypoint
    {
        private Vector3 position;

        /// <summary>
        /// Gets or sets the position.
        /// </summary>
        /// <value>The position.</value>
        public Vector3 Position
        {
            get { return position; }
            set { position = value; }
        }

        private WaypointType waypointType;

        /// <summary>
        /// Gets or sets the type of the waypoint.
        /// </summary>
        /// <value>The type of the waypoint.</value>
        public WaypointType WaypointType
        {
            get { return waypointType; }
            set { waypointType = value; }
        }

        private string name;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }

    public enum WaypointType
    {
        Navigation,
        Assault,
        Defend,
        Watch,
        Hold,
    }

    #endregion
}